{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 完成对facebook数据的k近邻的机器学习，并通过网格搜索找到最佳的kneighbors",
   "id": "ec3ca023199cd487"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:09.999703Z",
     "start_time": "2025-03-02T01:36:05.605713Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "import pandas as pd\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.model_selection import train_test_split"
   ],
   "id": "8c10741578ae2d21",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "cb9e2390cba6657a"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 数据预处理",
   "id": "3f30dfa6cc787a20"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "加载数据",
   "id": "b8ca4f21dc3dcbf1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.391132Z",
     "start_time": "2025-03-02T01:36:09.999703Z"
    }
   },
   "cell_type": "code",
   "source": "data = pd.read_csv(\"./train.csv\")",
   "id": "8b8355b8a2853b0",
   "outputs": [],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.690794Z",
     "start_time": "2025-03-02T01:36:16.391132Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(type(data))\n",
    "print(data.head(2))\n",
    "print(data.shape)\n",
    "data = data.query(\"x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75\")  # .query()方法可以查询数据，这里是选取x,y在1.0到1.25,2.5到2.75之间的样本\n",
    "time_values = pd.to_datetime(data['time'], unit='s')  # 将时间戳转换为日期格式\n",
    "print(time_values.head(2))\n",
    "time_values = pd.DatetimeIndex(time_values)  # 将日期格式转换为DatetimeIndex格式,返回的类型为DatetimeIndex\n",
    "print(type(time_values))\n",
    "print(time_values[:4])"
   ],
   "id": "2d8db46315395a18",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "   row_id       x       y  accuracy    time    place_id\n",
      "0       0  0.7941  9.0809        54  470702  8523065625\n",
      "1       1  5.9567  4.7968        13  186555  1757726713\n",
      "(29118021, 6)\n",
      "600   1970-01-01 18:09:40\n",
      "957   1970-01-10 02:11:10\n",
      "Name: time, dtype: datetime64[ns]\n",
      "<class 'pandas.core.indexes.datetimes.DatetimeIndex'>\n",
      "DatetimeIndex(['1970-01-01 18:09:40', '1970-01-10 02:11:10',\n",
      "               '1970-01-05 15:08:02', '1970-01-06 23:03:03'],\n",
      "              dtype='datetime64[ns]', name='time', freq=None)\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "把时间转为日时周",
   "id": "d14d4258441812cb"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.700769Z",
     "start_time": "2025-03-02T01:36:16.690794Z"
    }
   },
   "cell_type": "code",
   "source": [
    "data.insert(data.shape[1], 'day', time_values.day)  #data.shape[1]是代表插入到最后的意思,一个月的哪一天\n",
    "data.insert(data.shape[1], 'hour', time_values.hour)\n",
    "data.insert(data.shape[1], 'weekday', time_values.weekday)\n",
    "data = data.drop('time', axis=1)\n",
    "data.head()"
   ],
   "id": "99b64080dea401b6",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "      row_id       x       y  accuracy    place_id  day  hour  weekday\n",
       "600      600  1.2214  2.7023        17  6683426742    1    18        3\n",
       "957      957  1.1832  2.6891        58  6683426742   10     2        5\n",
       "4345    4345  1.1935  2.6550        11  6889790653    5    15        0\n",
       "4735    4735  1.1452  2.6074        49  6822359752    6    23        1\n",
       "5580    5580  1.0089  2.7287        19  1527921905    9    11        4"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>row_id</th>\n",
       "      <th>x</th>\n",
       "      <th>y</th>\n",
       "      <th>accuracy</th>\n",
       "      <th>place_id</th>\n",
       "      <th>day</th>\n",
       "      <th>hour</th>\n",
       "      <th>weekday</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>600</th>\n",
       "      <td>600</td>\n",
       "      <td>1.2214</td>\n",
       "      <td>2.7023</td>\n",
       "      <td>17</td>\n",
       "      <td>6683426742</td>\n",
       "      <td>1</td>\n",
       "      <td>18</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>957</th>\n",
       "      <td>957</td>\n",
       "      <td>1.1832</td>\n",
       "      <td>2.6891</td>\n",
       "      <td>58</td>\n",
       "      <td>6683426742</td>\n",
       "      <td>10</td>\n",
       "      <td>2</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4345</th>\n",
       "      <td>4345</td>\n",
       "      <td>1.1935</td>\n",
       "      <td>2.6550</td>\n",
       "      <td>11</td>\n",
       "      <td>6889790653</td>\n",
       "      <td>5</td>\n",
       "      <td>15</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4735</th>\n",
       "      <td>4735</td>\n",
       "      <td>1.1452</td>\n",
       "      <td>2.6074</td>\n",
       "      <td>49</td>\n",
       "      <td>6822359752</td>\n",
       "      <td>6</td>\n",
       "      <td>23</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5580</th>\n",
       "      <td>5580</td>\n",
       "      <td>1.0089</td>\n",
       "      <td>2.7287</td>\n",
       "      <td>19</td>\n",
       "      <td>1527921905</td>\n",
       "      <td>9</td>\n",
       "      <td>11</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.711829Z",
     "start_time": "2025-03-02T01:36:16.701772Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 把签到数量少于n个目标位置删除，place_id是标签，即目标值\n",
    "place_count = data.groupby('place_id').count()\n",
    "place_count.describe()\n",
    "tf = place_count[place_count.row_id > 3].reset_index()  # 选择place_id的行数大于3的,并重置索引\n",
    "data = data[data['place_id'].isin(tf.place_id)]  # 选择place_id的行数大于3的\n",
    "data.head()\n",
    "y = data['place_id']  # 目标值\n",
    "x = data.drop(['place_id'], axis=1)  # 特征值\n",
    "x = x.drop(['row_id'], axis=1)  # 特征值"
   ],
   "id": "cfa370f94375f7f6",
   "outputs": [],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "进行数据集标准化和数据集划分",
   "id": "81ccb89a0de323be"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.723578Z",
     "start_time": "2025-03-02T01:36:16.712833Z"
    }
   },
   "cell_type": "code",
   "source": [
    "x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=1)\n",
    "# 特征工程（标准化）,下面3行注释，一开始我们不进行标准化，看下效果，目标值要不要标准化？  什么情况下进行标准化？\n"
   ],
   "id": "6e40b6ba1940a48d",
   "outputs": [],
   "execution_count": 6
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 特征工程",
   "id": "fa4c22b3db7c8fa1"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": [
    "std = StandardScaler()  # 实例化一个StandardScaler对象\n",
    "x_train = std.fit_transform(x_train)    # 训练集标准化\n",
    "x_test = std.transform(x_test)  #transfrom不再进行均值和方差的计算，是在原有的基础上去标准化"
   ],
   "id": "8f594844a487b1b4"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "64ac8fce2728fc2a"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 机器学习模型选择",
   "id": "e1c04a388363f854"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.816278Z",
     "start_time": "2025-03-02T01:36:16.723578Z"
    }
   },
   "cell_type": "code",
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=5,weights='distance')    # 设置超参数：n_neighbors:意思是选择最近的k个邻居，weights:意思是选择距离远近的权重，uniform是均匀权重，distance是距离权重\n",
    "knn.fit(x_train, y_train)  # 训练模型\n",
    "y_pred = knn.predict(x_test)  # 预测结果\n",
    "print(\"准确率:\", knn.score(x_test, y_test))  # 预测准确率 "
   ],
   "id": "833bd6f22f652d5b",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率: 0.4900709219858156\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 通过网格搜索找到最佳的",
   "id": "8a2b6abd222bfd6"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:16.819076Z",
     "start_time": "2025-03-02T01:36:16.816278Z"
    }
   },
   "cell_type": "code",
   "source": "from sklearn.model_selection import GridSearchCV",
   "id": "46edd44bf393ba25",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T01:36:19.480439Z",
     "start_time": "2025-03-02T01:36:16.819076Z"
    }
   },
   "cell_type": "code",
   "source": [
    "param = {'n_neighbors': [3, 5, 7, 9, 11, 13], 'weights': ['uniform', 'distance']}\n",
    "# 进行网格搜索，cv=3是3折交叉验证，用其中2折训练，1折验证\n",
    "gc = GridSearchCV(KNeighborsClassifier(), param, cv=3)\n",
    "gc.fit(x_train, y_train)  #你给它的x_train，它又分为训练集，验证集\n",
    "# 预测准确率，为了给大家看看\n",
    "print(\"在测试集上准确率：\", gc.score(x_test, y_test))\n",
    "print(\"在交叉验证当中最好的结果：\", gc.best_score_)  #最好的结果\n",
    "print(\"选择最好的模型是：\", gc.best_estimator_)  #最好的模型,告诉你用了哪些参数\n",
    "print(\"每个超参数每次交叉验证的结果：\")\n",
    "gc.cv_results_"
   ],
   "id": "e285d5b2e68b894d",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\陈其志\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\model_selection\\_split.py:805: UserWarning: The least populated class in y has only 1 members, which is less than n_splits=3.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在测试集上准确率： 0.4978723404255319\n",
      "在交叉验证当中最好的结果： 0.48132097020069126\n",
      "选择最好的模型是： KNeighborsClassifier(n_neighbors=13, weights='distance')\n",
      "每个超参数每次交叉验证的结果：\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'mean_fit_time': array([0.00585326, 0.00567842, 0.00634273, 0.00634464, 0.00651455,\n",
       "        0.00608993, 0.00555062, 0.00617536, 0.00570639, 0.00581304,\n",
       "        0.00550413, 0.00550183]),\n",
       " 'std_fit_time': array([4.68916650e-04, 2.27219035e-04, 3.04390369e-04, 8.50962398e-04,\n",
       "        8.98640920e-06, 7.50379088e-04, 5.90598321e-05, 2.41889354e-04,\n",
       "        4.94618189e-04, 4.94904802e-04, 4.06564058e-04, 4.08998129e-04]),\n",
       " 'mean_score_time': array([0.080489  , 0.03140585, 0.08995072, 0.03590846, 0.08293955,\n",
       "        0.04460748, 0.08524577, 0.04715387, 0.08707078, 0.05227129,\n",
       "        0.09049352, 0.0557553 ]),\n",
       " 'std_score_time': array([0.00965441, 0.00023518, 0.00870448, 0.00126493, 0.00166869,\n",
       "        0.00039484, 0.00162044, 0.0007708 , 0.00082069, 0.00052968,\n",
       "        0.00108035, 0.00043577]),\n",
       " 'param_n_neighbors': masked_array(data=[3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False, False, False],\n",
       "        fill_value=999999),\n",
       " 'param_weights': masked_array(data=['uniform', 'distance', 'uniform', 'distance',\n",
       "                    'uniform', 'distance', 'uniform', 'distance',\n",
       "                    'uniform', 'distance', 'uniform', 'distance'],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False, False, False],\n",
       "        fill_value=np.str_('?'),\n",
       "             dtype=object),\n",
       " 'params': [{'n_neighbors': 3, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 3, 'weights': 'distance'},\n",
       "  {'n_neighbors': 5, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 5, 'weights': 'distance'},\n",
       "  {'n_neighbors': 7, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 7, 'weights': 'distance'},\n",
       "  {'n_neighbors': 9, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 9, 'weights': 'distance'},\n",
       "  {'n_neighbors': 11, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 11, 'weights': 'distance'},\n",
       "  {'n_neighbors': 13, 'weights': 'uniform'},\n",
       "  {'n_neighbors': 13, 'weights': 'distance'}],\n",
       " 'split0_test_score': array([0.44468085, 0.4534279 , 0.4607565 , 0.47399527, 0.46501182,\n",
       "        0.47990544, 0.46453901, 0.48061466, 0.45910165, 0.47777778,\n",
       "        0.45579196, 0.48085106]),\n",
       " 'split1_test_score': array([0.43390873, 0.4542445 , 0.45660913, 0.47528967, 0.46275715,\n",
       "        0.47978245, 0.45566328, 0.4769449 , 0.4542445 , 0.48001892,\n",
       "        0.45471743, 0.4788366 ]),\n",
       " 'split2_test_score': array([0.43982029, 0.4561362 , 0.45684559, 0.47221565, 0.46346654,\n",
       "        0.47907307, 0.46157484, 0.47836368, 0.46039253, 0.48332939,\n",
       "        0.46039253, 0.48427524]),\n",
       " 'mean_test_score': array([0.43946996, 0.45460287, 0.45807041, 0.47383353, 0.46374517,\n",
       "        0.47958699, 0.46059237, 0.47864108, 0.45791289, 0.48037536,\n",
       "        0.45696731, 0.48132097]),\n",
       " 'std_test_score': array([0.00440467, 0.00113433, 0.00190181, 0.00126016, 0.00094131,\n",
       "        0.00036685, 0.0036895 , 0.00151096, 0.00264694, 0.00228041,\n",
       "        0.0024614 , 0.00224504]),\n",
       " 'rank_test_score': array([12, 11,  8,  5,  6,  3,  7,  4,  9,  2, 10,  1], dtype=int32)}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "638bb8087b5973b0"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
